/*
 * PriceEvolution.java
 *
 */

package market;

import java.io.BufferedReader;
import java.util.ArrayList;
import java.util.Random;
import java.util.TimerTask;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.jms.Topic;
import javax.jms.TopicConnection;
import javax.jms.TopicConnectionFactory;
import javax.jms.TopicPublisher;
import javax.jms.TopicSession;

/**
 * This object changes the market prices
 */
public class PPriceEvolution  extends TimerTask implements MessageListener{
    
    private ArrayList stockList;
    private javax.swing.JList jListEvent;
    private LogList logList;
    final int MSGT_CHANGE_PRICE = 6;
    final double PROBA_EVO = 0.05;//Probability of a large rate change
    final double EXCEPTIONAL_EVO_RATE = 0.5;//Rate of increase/decrease when large change
    final double NORMAL_EVO_RATE = 0.1;//Normal increase/decrease rate
    final double PROBA_UP = 0.475;//If random bigger than PROBA_UP => INCREASE
    final double PROBA_DOWN = 0.575;//If random smaller than PROBA_DOWN => DECREASE
    final double PRICE_ROOF = 0.5;//Minimal price
    
    /** Creates a new instance of PriceEvolution */
    public PPriceEvolution(javax.swing.JList jListEvent,ArrayList pdtList) {
        
        this.logList = new LogList();
        this.logList.add("Application ready to listen for messages !");

        //Get list at the instantiation
        this.jListEvent = jListEvent;
        
        this.setStockList(pdtList);
        
        //Setting in the JTable
        jListEvent.setListData(this.logList.toArray());

        //add the message queue listener
        String queueName = "transaction";
        ConnectionFactory connectionFactory = new com.sun.messaging.ConnectionFactory();
        Connection connection = null;
        try {
            connection = connectionFactory.createConnection();
            Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
            Queue queue = new com.sun.messaging.Queue(queueName);
            MessageConsumer consumer = session.createConsumer(queue);
            MessageListener listener = this;
            consumer.setMessageListener(listener);
            connection.start();
            //lpf, ca sert a quoi ??
            synchronized (listener) {
        //        listener.wait();
            }
        } catch (Exception e) {
            System.out.println("Exception occurred: " + e.toString());
            System.exit(1);
        }
    }
    
    /**
     * This method modifies market prices
     * Called by a Timer
     */
    public void run() {
        boolean sendThis = false;
        double newPrice = 0;
        if (getStockList() != null){
            java.util.Iterator it = getStockList().iterator();
            while(it.hasNext()){
                java.util.Random randomizer;
                StockProduct thisStock = (StockProduct) it.next();
                double proba ;
                randomizer = new Random();
                proba=randomizer.nextDouble();
                if (thisStock.getStockPrice().doubleValue()<=(new Double(0.5)).doubleValue()){
                    newPrice = Math.round(new Double(randomizer.nextDouble()).doubleValue()*100);
                    sendThis = true;
                }else {
                    double coef=0;
                    if (randomizer.nextDouble()<=PROBA_EVO){
                        coef = EXCEPTIONAL_EVO_RATE;
                    } else {
                        coef = NORMAL_EVO_RATE;
                    }
                    if (proba >= PROBA_UP ) {//Increase
                        newPrice = Math.round((thisStock.getStockPrice().doubleValue()*(new Double(1).doubleValue()+new Double(randomizer.nextDouble()*coef).doubleValue())));
                        sendThis = true;
                    } else if ((proba <= PROBA_DOWN) && (thisStock.getStockPrice().doubleValue()>=(new Double(PRICE_ROOF)).doubleValue())){//Decrease only if the price is over 0.5
                        newPrice = Math.round((thisStock.getStockPrice().doubleValue()*(new Double(1).doubleValue()-new Double(randomizer.nextDouble()*coef).doubleValue())));
                        if (newPrice <=PRICE_ROOF){
                            sendThis=false;
                        }else{
                            sendThis = true;
                        }
                    } else {//No change
                        sendThis = false;
                    }
                }
                if (sendThis){
                    //Price modification
                    try {
                        thisStock.setStockPrice(newPrice);
                        String newLine = "Message sends to set "+thisStock.getStockID()+" new price : "+newPrice;
                        this.logList.addReverse(newLine);
                    }catch (Exception e){
                        String newLine = "Problem sending message to set "+thisStock.getStockID()+" new price.";
                        this.logList.addReverse(newLine);
                    }


                    /*publish the price*/
                    String topicName = "price";
                    TopicConnectionFactory connectionFactory = new com.sun.messaging.TopicConnectionFactory();
                    TopicConnection connection = null;
                    try {
                        connection = connectionFactory.createTopicConnection();
                        TopicSession session = connection.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
                        Topic topic = session.createTopic(topicName);
                        TopicPublisher publisher = session.createPublisher(topic);
                        TextMessage message = session.createTextMessage();

                        message.setText(thisStock.getStockID()+"%"+newPrice);
                        System.out.println("Publishing \"" + message.getText() + "\"");
                        publisher.publish(message);
                    } catch (Exception e) {
                        System.out.println("Exception occurred: " + e.toString());
                        System.exit(1);
                    }




                }
                sendThis=false;
            }
            jListEvent.setListData(this.logList.toArray());
        }
    }



    public ArrayList getStockList() {
        return stockList;
    }
    
    public void setStockList(ArrayList stockList) {
        this.stockList = stockList;
    }
    
    public LogList getLogList() {
        return logList;
    }
    
    public void setLogList(LogList logList) {
        this.logList = logList;
    }

    public void onMessage(Message msg) {

        System.out.println(msg);
        this.logList.addReverse(msg);
    
    }
}